package com.ppch.zerocodegenerator.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.ppch.zerocodegenerator.exception.BusinessException;
import com.ppch.zerocodegenerator.exception.ErrorCode;
import com.ppch.zerocodegenerator.exception.ThrowUtils;
import com.ppch.zerocodegenerator.mapper.UserMapper;
import com.ppch.zerocodegenerator.model.constant.UserConstant;
import com.ppch.zerocodegenerator.model.dto.user.UserLoginRequest;
import com.ppch.zerocodegenerator.model.dto.user.UserModifyPassWord;
import com.ppch.zerocodegenerator.model.dto.user.UserQueryRequest;
import com.ppch.zerocodegenerator.model.dto.user.UserRegisterRequest;
import com.ppch.zerocodegenerator.model.entity.User;
import com.ppch.zerocodegenerator.model.enums.UserRoleEnum;
import com.ppch.zerocodegenerator.model.vo.LoginUserVO;
import com.ppch.zerocodegenerator.model.vo.UserVO;
import com.ppch.zerocodegenerator.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.ppch.zerocodegenerator.model.constant.UserConstant.USER_LOGIN_STATE;


/**
* @author 鲸落
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2025-08-11 14:11:25
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;


    /**
     * 用户注册
     *
     * @param userRegisterRequest 用户注册请求类
     * @return Long 影响数据行数
     */
    @Override
    public long userRegister(UserRegisterRequest userRegisterRequest) {
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        //1.数据校验
        ThrowUtils.throwIf(ObjectUtil.isEmpty(userRegisterRequest), ErrorCode.PARAMS_ERROR, "请求参数对象为空");
        ThrowUtils.throwIf(StrUtil.isBlank(userAccount), ErrorCode.PARAMS_ERROR, "用户账号为空");
        ThrowUtils.throwIf(StrUtil.isBlank(userPassword), ErrorCode.PARAMS_ERROR, "密码为空");
        ThrowUtils.throwIf(StrUtil.isBlank(checkPassword), ErrorCode.PARAMS_ERROR, "确认密码为空");
        ThrowUtils.throwIf(userAccount.length() < 4, ErrorCode.PARAMS_ERROR, "用户账号过短（不小于4位）");
        ThrowUtils.throwIf(userPassword.length() < 8, ErrorCode.PARAMS_ERROR, "密码过短（不小于8位）");
        ThrowUtils.throwIf(!userPassword.equals(checkPassword), ErrorCode.PARAMS_ERROR, "密码与确认密码不一致");
        //2.校验用户账号是否重复
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(User::getUserAccount, userAccount);
        //根据用户账号查询符合条件的信息条数,如果 >= 1 表示该账号已存在
        Long count = userMapper.selectCountByQuery(queryWrapper);
        ThrowUtils.throwIf(count >= 1, ErrorCode.PARAMS_ERROR, "用户账号已存在");
        //3.密码加密
        String encryptPassword = encryptPassword(userPassword);
        //4.插入数据到数据库中
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setUserName("无名氏");
        user.setUserProfile("这个人很神秘，什么都没有写");
        user.setUserAvatar(getRandomAvatar()); // 设置随机头像
        user.setUserRole(UserRoleEnum.USER.getValue());
        //insertSelective:插入实体类数据，但是忽略 null 的数据，并返回影响行数
        int result = userMapper.insertSelective(user);
        ThrowUtils.throwIf(result != 1, ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
        // mybatis 特性：主键回填
        return user.getId();
    }


    /**
     * 用户登录
     *
     * @param userLoginRequest 用户账号 用户密码
     * @param request          请求对象
     * @return 脱敏后的用户信息
     */
    @Override
    public LoginUserVO userLogin(UserLoginRequest userLoginRequest, HttpServletRequest request) {
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        //获取加密后的密码
        String encryptPassword = encryptPassword(userPassword);
        //1.校验参数
        ThrowUtils.throwIf(StrUtil.isBlank(userAccount), ErrorCode.PARAMS_ERROR, "用户账号为空");
        ThrowUtils.throwIf(StrUtil.isBlank(userPassword), ErrorCode.PARAMS_ERROR, "密码为空");
        //2.根据用户账号和密码查询数据库，判断用户是否存在或密码是否错误
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(User::getUserAccount, userAccount);
        queryWrapper.eq(User::getUserPassword, encryptPassword);
        //查询到的用户对象
        User user = userMapper.selectOneByQuery(queryWrapper);
        //3.如果数据不存在：报错；
        if (user == null) {
            log.error("用户登录错误：用户不存在或密码错误");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        }
        //存在：保存用户登录态（session）
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        //信息脱敏
        return getLoginUserVO(user);
    }

    /**
     * 获取当前登录用户信息
     * 1.为了保证数据一致性：最好是从数据库中再查一遍，防止session中的数据与数据库中的数据不一致
     *
     * @param request HttpServletRequest
     * @return User
     */
    @Override
    public User getLoginUser(HttpServletRequest request) {
        //从session中获取当前登录用户信息
        Object attribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = (User) attribute;
        if (currentUser == null || currentUser.getId() == null) {
            //未登录
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //为了保证数据一致性：最好是从数据库中再查一遍，防止session中的数据与数据库中的数据不一致
        Long currentUserId = currentUser.getId();
        User user = userMapper.selectOneById(currentUserId);
        if (user == null) {
            //未登录
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return user;
    }

    /**
     * 用户退出登录
     *
     * @param request HttpServletRequest
     * @return boolean
     */
    @Override
    public boolean userLogout(HttpServletRequest request) {
        //1.首先判断用户是否登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (userObj == null) {
            //未登录
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户未登录");
        }
        //2.如果登录了：将session中的用户信息移除
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    /**
     * 修改密码
     *
     * @param userModifyPassWord 修改密码实体类
     * @param request HttpServletRequest
     * @return boolean
     */
    @Override
    public boolean changePassword(UserModifyPassWord userModifyPassWord, HttpServletRequest request) {
        if (StrUtil.hasBlank(userModifyPassWord.getOldPassword(), userModifyPassWord.getNewPassword(), userModifyPassWord.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数不能为空");
        }
        if (!userModifyPassWord.getNewPassword().equals(userModifyPassWord.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        if (userModifyPassWord.getNewPassword().length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "新密码长度不能小于8位");
        }
        //查询是否有这个用户
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(User::getId, userModifyPassWord.getId());
        String encryptPassword = encryptPassword(userModifyPassWord.getOldPassword());
        queryWrapper.eq(User::getUserPassword, encryptPassword);
        User user = userMapper.selectOneByQuery(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "原密码错误");
        }
        user.setUserPassword(encryptPassword(userModifyPassWord.getNewPassword()));
        // 更新MySQL
        boolean result = userMapper.update(user) > 0;

        return result;
    }

    /**
     * 重置密码
     * @param loginUser 当前登录用户
     * @param newPassword 新密码
     * @param checkPassword 确认密码
     * @return 是否重置成功
     */
    @Override
    public boolean resetPassword(User loginUser, String newPassword, String checkPassword) {
        Long id = loginUser.getId();
        // 1. 校验参数
        if (StrUtil.hasBlank(newPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (ObjectUtil.isEmpty(loginUser)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        // 3. 校验密码
        if (newPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度不能小于8位");
        }
        if (!newPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        // 5. 查询用户是否存在
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(User::getId, id);
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        // 6. 更新密码
        String encryptPassword = encryptPassword(newPassword);
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setUserPassword(encryptPassword);
        boolean result = this.updateById(updateUser);
        return result;
    }

    /**
     * 更新用户头像
     * @param multipartFile 头像图片文件
     * @param id 用户id
     * @return 更新后的图片URL
     */
    @Override
    public String updateUserAvatar(MultipartFile multipartFile, Long id, HttpServletRequest request) {
        //判断用户是否存在
        User user = userMapper.selectOneById(id);
        if(user == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        //判断用户是否登录
        User loginUser = getLoginUser(request);
        if(loginUser == null || !loginUser.getId().equals(id)){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        //判断文件是否为空
        if(multipartFile == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件不能为空");
        }
       /* //判断文件类型
        // 上传图片，得到图片信息
        // 保存到cos对象存储中的avatar目录
        String uploadPathPrefix = "/avatar";
        UploadPictureResult uploadPictureResult = fileManager.uploadPicture(multipartFile, uploadPathPrefix);
        //更新用户头像
        user.setUserAvatar(uploadPictureResult.getThumbnailUrl());
        // 更新MySQL
        int result = userMapper.updateById(user);
        if (result != 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新数据库失败");
        }
        return uploadPictureResult.getThumbnailUrl();*/
        return "";
    }

    /**
     * 获取加密后的密码
     *
     * @param default_password 默认密码
     * @return 加密后的密码
     */
    @Override
    public String getEncryptPassword(String default_password) {
        return encryptPassword(default_password);
    }

    /**
     * 登录用户信息脱敏
     *
     * @param user 用户信息对象
     * @return LoginUserVO 脱敏后的登录用户信息
     */
    @Override
    public LoginUserVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtils.copyProperties(user, loginUserVO);
        return loginUserVO;
    }

    /**
     * 用户信息脱敏
     *
     * @param user 用户信息对象
     * @return UserVO 脱敏后的用户信息
     */
    @Override
    public UserVO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }


    /**
     * 获取用户列表（脱敏后）
     * @param userList 用户列表
     * @return 用户列表
     */
    @Override
    public List<UserVO> getUserVOList(List<User> userList) {
        if (CollUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        return userList.stream().map(this::getUserVO).collect(Collectors.toList());
    }


    /**
     * 密码加密
     *
     * @param password 用户输入密码
     * @return encryptPassword 加密后的密码
     */
    public String encryptPassword(String password) {
        final String SALT = "ppch";
        byte[] bytes = (SALT + password).getBytes();
        String encryptPassword = DigestUtils.md5DigestAsHex(bytes);
        return encryptPassword;
    }

    /**
     * 从六个头像中随机获取一个头像
     *
     * @return 头像url链接
     */
    public String getRandomAvatar() {
        String kaixingchaoren = "https://pic1.zhimg.com/v2-4e7f93275a2f7100bebdd93ae1e4188c_r.jpg";
        String huaxingchaoren = "https://pic4.zhimg.com/80/v2-0dbc479a4fa0f130a1622e36b9f43057_720w.jpg";
        String konlong  = "https://tse1-mm.cn.bing.net/th/id/OIP-C.Knh5i_ceDHm_cwzEcKFJ2gAAAA?w=217&h=217&c=7&r=0&o=7&cb=12&dpr=2&pid=1.7&rm=3";
        String leisai  = "https://tse1-mm.cn.bing.net/th/id/OIP-C.DqL1pjvmiQHiLqoA9_8PmQHaHT?w=203&h=201&c=7&r=0&o=7&cb=12&dpr=2&pid=1.7&rm=3";
        String erciyuan  = "https://tse3-mm.cn.bing.net/th/id/OIP-C.JghYq3q7DmnZqp51q4G5LAHaHa?w=192&h=191&c=7&r=0&o=7&cb=12&dpr=2&pid=1.7&rm=3";
        String hongxiaodou  = "https://ts1.tc.mm.bing.net/th/id/OIP-C.GABSNBeQIGgYnT9WaA6WHwAAAA?w=186&h=186&c=8&rs=1&qlt=90&o=6&cb=12&dpr=2&pid=3.1&rm=2";

        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(kaixingchaoren);
        arrayList.add(huaxingchaoren);
        arrayList.add(konlong);
        arrayList.add(leisai);
        arrayList.add(erciyuan);
        arrayList.add(hongxiaodou);
        int i = RandomUtil.randomInt(arrayList.size());
        String avatar = arrayList.get(i);
        return avatar;
    }

    /**
     * 获取 mybatis 组合查询条件
     * 注意：字符串用 isNotBlank，isBlank 判断是否为空
     * 因为该方法判断字符串是否为非空白，非空白的定义如下：
     * 不为 null
     * 不为空字符串：""
     * 不为空格、全角空格、制表符、换行符，等不可见字符
     *
     * @param userQueryRequest 用户查询请求实体
     * @return QueryWrapper<User>
     */
    @Override
    public QueryWrapper getUserQueryWrapper(UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Long id = userQueryRequest.getId();
        String userAccount = userQueryRequest.getUserAccount();
        String userName = userQueryRequest.getUserName();
        String userProfile = userQueryRequest.getUserProfile();
        String userRole = userQueryRequest.getUserRole();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();
        return QueryWrapper.create()
                .eq(User::getId, id)
                .eq(User::getUserRole, userRole)
                .like(User::getUserAccount, userAccount)
                .like(User::getUserName, userName)
                .like(User::getUserProfile, userProfile)
                .orderBy(sortField, "ascend".equals(sortOrder));
    }




    /**
     * 判断用户是否为管理员
     *
     * @param user 用户信息
     * @return boolean true:是管理员 false：不是管理员
     */
    @Override
    public boolean isAdmin(User user) {
        //当用户对象不为空且用户角色为管理员时，才返回true；否则返回false。
        return user != null && UserConstant.ADMIN_ROLE.equals(user.getUserRole());
    }


}




